import java.net.InetAddress;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;

/*
 *  1. Recoit les appels des clients (couche Client).
 *  2. Redirige chaque appel vers le ServerObject associe.
 *  3. Quand le serveur reclame un verrou au client:
 *     (invalidate_reader/invalidate_writer/reduce_lock),Si le verrou est tenu, 
 *     Il faut attendre.
 *  4. Un unlock appelle notify().(Client?)
 *  5. Une reclamation (dans SharedObject) appelle wait() si le verrou est tenu(Client?)
 * */
public class Server implements Server_itf {

	private static HashMap<String, Integer> server_nom;
	private static HashMap<Integer, SharedObject> sharedObjects;
	private static HashMap<Integer, ServerObject> serverObjects;

	@Override
	public int lookup(String name) throws RemoteException {
		return server_nom.get(name);
	}

	@Override
	public void register(String name, int id) throws RemoteException {
		server_nom.put(name, id);
	}

	@Override
	public int create(Object o) throws RemoteException {
		int id = server_nom.size();
		SharedObject sharedObject = new SharedObject(id, o);
		ServerObject serverObject = new ServerObject(id, o);
		sharedObjects.put(id, sharedObject);
		serverObjects.put(id, serverObject);
		return id;
	}

	@Override
	/**
	 * Appels a distance (RMI) Ces méthodes incluent une référence au client
	 * afin de pouvoir le rappeler ultérieurement.
	 */
	public Object lock_read(int id, Client_itf client) throws RemoteException {
		return serverObjects.get(id).lock_read(client);
	}

	@Override
	/**
	 * Appels a distance (RMI) Ces méthodes incluent une référence au client
	 * afin de pouvoir le rappeler ultérieurement.
	 */
	public Object lock_write(int id, Client_itf client) throws RemoteException {
		return serverObjects.get(id).lock_write(client);
	}

	public static void main(String args[]) {
		String URL = "";
		int port = 5000;
		try {
			// creation du serveur de nom - rmiregistry
			Registry registry = LocateRegistry.createRegistry(port);
			// creation d'une instance de l'objet serveur
			Server s = new Server();
			// calcul de l'URL du serveur
			URL = "//" + InetAddress.getLocalHost().getHostName() + ":" + port
					+ "/mon_serveur";
			Naming.rebind(URL, s);
		} catch (Exception e) {
			System.out.println("probleme lors de l'initialisation du serveur");
		}
	}

	/**
	 * return SharedObject by id;
	 */
	public SharedObject getSharedObjectById(int id) {
		return sharedObjects.get(new Integer(id));
	}
}
